<!DOCTYPE html>
<html lang="en">

<head>
    <title>easyAi开发文档</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
        integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <!-- <link rel="stylesheet" href="type.css"> -->
    <style>
        ul li {
            list-style: none;
            font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
            color: #1874CD;
        }

        h3 {
            color: #FF4040;
            font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
            font-size: 20px;
        }

        h5 {
            font-weight: bold;
            font-size: 20px;
        }

        .normTxt {
            font-size: 16px;
            font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
        }

        .top {
            margin-top: 30px;
        }

        #edition {
            font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
            font-size: 18px;
        }

        p {
            margin-top: 20px;
        }

        .lv1 {
            font-size: 17px;
        }

        .lv2 {
            font-size: 15px;
        }
    </style>
</head>

<body>
    <div class="row">
        <div class="col-md-1"></div>
        <div class="page-header col-md-9">
            <h1>EASYAI开发文档 <small>开源版</small></h1>
        </div>
    </div>
    <div class="row">
        <div class="col-md-1"></div>
        <div class="col-md-9">
            <ul>
                <h3>目录</h3>
                <li class="lv1"><a href="#start">快速开始</a>
                    <ul>
                        <li class="lv2"><a href="#oneLook">图像识别</a></li>
                        <li class="lv2"><a href="#getModel">图片摘要</a></li>
                        <li class="lv2"><a href="#insertModel">语义理解</a></li>
                        <li class="lv2"><a href="#cutting">拆词分词</a></li>
                        <li class="lv2"><a href="#manyLook">捕捉关键词</a></li>
                        <li class="lv2"><a href="#word">词语补全</a></li>
                    </ul>
                </li>
                <li class="lv1"><a href="#tools">分类工具</a>
                    <ul>
                        <li class="lv2"><a href="#nerve">深度神经网络</a></li>
                        <li class="lv2"><a href="#RF">随机森林</a></li>
                        <li class="lv2"><a href="#knn">KNN</a></li>
                    </ul>
                </li>
                <li class="lv1"><a href="#jutools">聚类工具</a>
                    <ul>
                        <li class="lv2"><a href="#lvq">LVQ</a></li>
                        <li class="lv2"><a href="#kavg">原型聚类</a></li>
                    </ul>
                </li>
                <li class="lv1"><a href="#arouse">启发式工具</a>
                    <ul>
                        <li class="lv2"><a href="#pso">粒子群</a></li>
                    </ul>
                </li>
                <li class="lv1"><a href="#Intensive">强化学习工具</a>
                    <ul>
                        <li class="lv2"><a href="#DP">动态规划</a></li>
                    </ul>
                </li>
                <li class="lv1"><a href="#matrix">矩阵运算</a>
                </li>
                <li class="lv1"><a href="#picture">图像工具</a>
                    <ul>
                        <li class="lv2"><a href="#pictureTools">图像解析</a></li>
                    </ul>
                </li>
                <li class="lv1">持续更新
                </li>
            </ul>
            <h5 class="page-header"></h5>
        </div>
    </div>
    <div class="row">
        <div class="col-md-1"></div>
        <div class="col-md-9">
            <h4 id="edition">v1.0.6</h4>
            <div class="top">
                <p class="normTxt">easyAI是用来简易快速开发人工智能应用的JAVA引擎，也同时可以深度开发定制需求。本文档详细讲述本框架的所有即时更新版本内容，
                    详述所有内置API,内置参数，各种模式及应用，对于深度学习easyAI开发人员提供帮助。同时可以让企业低成本部署，快速应用落地，并降低人才门槛及费用。
                    <a href="https://www.bilibili.com/video/av89134035">点击可查看easyAi视频教程</a>，
                    <a href="https://gitee.com/ldp_dpsmax/easyAi">easyAi-1.0.6Maven包下载地址</a>
                </p>
                <div class="alert alert-success" role="alert">注意：凡事本文档中涉及图片尺寸的参数，其单位都为<strong>像素</strong></div>
                <h3 id="start">快速开始</h3>
                <h5 id="oneLook">图像识别：</h5>
                <div class="alert alert-info" role="alert">图像识别是人工智能的主流应用之一，主要是对图像进行切割和识别，但业务情景不同，方法区别明显较大。
                    就让我们首先从图像自主结算果蔬称识别开始。</div>
                <pre>Config config = new Config();//配置文件类;</pre>
                <p class="normTxt">配置文件类，这是一个用来保存学习过程中需要的各种参数，各种分类器参数及各种需要初始化的内部类。</p>
                <pre>config.setTypeNub(2);//设置训练种类数</pre>
                <pre>config.setBoxSize(125);//设置物体大致大小 单位像素 即 125*125 的矩形</pre>
                <pre>config.setPictureNumber(5);//设置每个种类训练图片数量 某个类别有几张照片，注意所有种类照片数量要保持一致</pre>
                <pre>config.setPth(0.7);//设置可信概率，只有超过可信概率阈值，得出的结果才是可信的 数值为0-1之间</pre>
                <pre>config.setShowLog(true);//输出学习时打印数据</pre>
                <p class="normTxt">图片解析与图片训练</p>
                <pre> Picture picture = new Picture();//图片解析类，用于将图片解析为三通道像素矩阵</pre>
                <pre> Distinguish distinguish = new Distinguish(config);//创建识别类</pre>
                <pre> distinguish.setBackGround(picture.getThreeMatrix("E:\\ls\\fp15\\back.jpg"));//设置识别的背景图片(该api为固定背景)</pre>
                <p class="normTxt">读取训练图片，进行图像训练</p>
                <pre>
        List&lt;FoodPicture&gt; foodPictures = new ArrayList<>();//所有识别物体的标注集合
        for (int i = 1; i < 3; i++) {//加载图片全过程
            FoodPicture foodPicture = new FoodPicture();
            foodPictures.add(foodPicture);
            List&lt;PicturePosition&gt; picturePositionList = new ArrayList&lt;&gt;();
            foodPicture.setId(i + 1);//该图片类别
            foodPicture.setPicturePositionList(picturePositionList);
            for (int j = 1; j < 6; j++) {
                String name;
                if (i == 1) {
                    name = "a";
                } else {
                    name = "b";
                }
                PicturePosition picturePosition = new PicturePosition();
                picturePosition.setUrl("E:\\ls\\fp15\\" + name + i + ".jpg");
                picturePosition.setNeedCut(false);//是否需要剪切，充满全图不需要
                picturePositionList.add(picturePosition);
            }
        }
        distinguish.studyImage(foodPictures);//进行学习 耗时较长</pre>
                <p class="normTxt">学习完成提取模型，并将模型myModel序列化为JSON字符串形式保存</p>
                <pre>  Model model = distinguish.getModel();String myModel= JSON.toJSONString(model);</pre>
                <p class="normTxt">服务启动初始化静态配置，并注入学习模型</p>
                <pre>
        Config config = new Config();//配置文件
        config.setTypeNub(2);//设置类别数量
        config.setBoxSize(125);//设置物体大小 单位像素
        config.setPictureNumber(5);//设置每个种类训练图片数量
        config.setPth(0.7);//设置可信概率，只有超过可信概率阈值，得出的结果才是可信的
        config.setShowLog(false);//输出学习时打印数据
        Distinguish distinguish = new Distinguish(config);//识别类
        distinguish.insertModel(JSONObject.parseObject(ModelData.DATA, Model.class));//将之前训练时保存的训练模型反序列化为实体类后，注入模型
        //注意：完成后请单例Distinguish类，即完成系统启动时初始化过程</pre>
                <p class="normTxt">识别过程</p>
                <div class="alert alert-danger" role="alert"><strong>注意：</strong>
                    <code>Distinguish distinguish</code> 此识别类为系统启动时已经单例初始化的，要获取从单例初始化已经完成，并注入模型后的Distinguish类，识别过程请不要 "new" 这个类。
                </div>
                <pre>
            Picture picture = new Picture();//图片解析类
            for (int i = 1; i < 8; i++) {
            System.out.println("i====" + i);
            ThreeChannelMatrix t = picture.getThreeMatrix("E:\\ls\\fp15\\t" + i + ".jpg");//将识别图片转化为矩阵
            Map&lt;Integer, Double&gt; map = distinguish.distinguish(t);//识别结果
            for (Map.Entry&lt;Integer, Double&gt; entry : map.entrySet()) {
                System.out.println(entry.getKey() + ":" + entry.getValue());//识别结果打印
            }
        }</pre>
                <p class="normTxt">识别结果打印控制台</p>
                <pre>
        i====1//第一张图 结果为 橘子，出现2：代表类别。:0.8874306751020916，带表该类别权重，权重越高说明该类别的物品在当前 图片中数量越多或者面积越大。
        2:0.8874306751020916 说明（图1有橘子，权重为：0.8874306751020916）
        i====2
        2:0.8878192183606407
        i====3
        3:0.7233916245920673说明（图3有苹果，权重为：0.7233916245920673）
        i====4
        2:0.9335699571468958说明（图4有橘子，权重为：0.9335699571468958）
        3:0.7750825597199661说明（图4有苹果，权重为：0.7750825597199661）
        i====5
        3:0.8481590575557582
        i====6
        2:0.7971025523095067
        i====7
        2:1.5584968376080388（图7有橘子，权重为：1.5584968376080388）
        3:0.8754957897385587（图7有苹果，权重为：0.8754957897385587）</pre>
                <div class="alert alert-info" role="alert">
                    本演示样例代码位置在： src/test/java/org/wlld/ImageTest.java</br>
                    本演示训练素材位置在： src/test/image</br>
                    <strong>注意：</strong>以上图片识别代码样例为训练素材为物品全图充满图片(自己看能看到橘子训练图片为全图充满，苹果也是).自行开发时用以上代码样例时，请也使用全图充满训练物品的图片来做训练。</div>
                <p class="normTxt" id="getModel">图片摘要</p>
                <div class="alert alert-success" role="alert">
                    <strong>图片摘要的目的：</strong>可以对图片快速生成一串字符串ID，用于通过对于字符串相似度对比就可快速对比图片相似度。
                </div>
                <div class="alert alert-warning" role="alert">
                    <strong>警告：</strong>通过图片摘要ID对比图片相似度，只能从构图色彩及结构对比，无法从语义级别对比相似度。
                </div>
                <div class="alert alert-info" role="alert">
                    <strong>参数说明：</strong>
                    <p>第一个参数：<code>threeChannelMatrix</code>图像三通道矩阵，通过<code>Picture</code>类读取本地文件或输入流获取，
                        前文代码有注释说明。</p>
                    <p>第二个参数：<code>boxSize</code>将一张图片横纵各分为几个区域提取特征，该值越大，生成的摘要id敏感度越高</p>
                    <p>第三个参数：<code>regionSize</code>相似特征区域分区种类数量，该值越大，生成的摘要id敏感度越高</p>
                    <p>最终返回<code>id</code>即为该图片摘要id，通过id逐位对比即可对比相似程度</p>
                </div>
                <pre>
FastPictureExcerpt fastPictureExcerpt = new FastPictureExcerpt();
String id = fastPictureExcerpt.creatImageName(threeChannelMatrix, 5, 10);</pre>
                <div class="alert alert-info" role="alert">
                    <strong>什么是id敏感度：</strong>
                   <p>id敏感度越高，对图片变化越敏感，越适合越大的检索区域匹配，即特征越细致，但缺点id长度越长。</p>
                    <p>id敏感度越低，对图片变化越不敏感，越适合越小的检索区域匹配,特征越粗，优点是id长度越短。</p>
                </div>
                <h5 id="insertModel">语义理解：</h5>
                <p class="normTxt">对语言训练模板进行初始化并学习</p>
                <pre>
WordTemple wordTemple = new WordTemple();
Tokenizer tokenizer = new Tokenizer(wordTemple);//学习类
Map&lt;Integer, List&lt;String&gt&gt; model = new HashMap&lt;&gt;();//训练模板 主键为类别id,值为该类别id的语句集合
tokenizer.start(model); //开始训练</pre>
                    <div class="alert alert-danger" role="alert"><strong>注意：</strong>
                        <p>最好不要将标点符号带入训练语句，在训练量不足的时候可以展现更好的效果</p>
                        <p>包含数字的语句用统一的占位符代替 例如 35,3,36% 变为 #,#,#%</p>
                        <p><code>wordTemple</code>初始化语言模版，该语言模板要进行单例化，在内存中长期持有。</p>
                    </div>
                <p class="normTxt" >对用户输入的语句进行语义分类</p>
                <pre>
Talk talk = new Talk(wordTemple);
List&lt;Integer&gt; list = talk.talk("空调坏了，帮我修一修");
System.out.println(list);
}</pre>
                <div class="alert alert-danger" role="alert"><strong>注意：</strong>
                  <p><code>list</code>返回的集合中每个值代表了输入语句在每个标点符号前语句的分类id</p>
                    <p><code>Talk</code>的构造参数<code>wordTemple</code>是初始化并训练时，内存中单例保存的wordTemple</p>
                </div>
                <p class="normTxt" id="cutting">纯切词模式</p>
                <div class="alert alert-danger" role="alert"><strong>注意：</strong>
                    <code>wordTemple.setSplitWord(true)</code>将模板设置成纯切词模式
                </div>
                <pre>
wordTemple.setSplitWord(true);
List&lt;List&lt;String&gt;&gt; lists = talk.getSplitWord("空调坏了，帮我修一修");
for (List&lt;String&gt; list : lists) {
System.out.println(list);
}</pre>
                <p class="normTxt" id="manyLook">捕捉用户输入语句的关键词</p>
                <pre>
CatchKeyWord catchKeyWord = new CatchKeyWord();
List&lt;KeyWordForSentence&gt; keyWordForSentenceList = new ArrayList&lt;&gt;();
            for (Sentence sentence : sentences) {
                String word = sentence.getWord();//模板中的用户语句
                String keyWord = sentence.getNoun();//该用户语句中的关键词
                if (keyWord != null && keyWord.length() > 0) {//关键词必须存在
                    KeyWordForSentence keyWordForSentence = new KeyWordForSentence();
                    keyWordForSentence.setSentence(word);//输入语句
                    keyWordForSentence.setKeyWord(keyWord);//输入关键词
                    keyWordForSentenceList.add(keyWordForSentence);
                }
            }
catchKeyWord.study(keyWordForSentenceList);//进行关键词训练
KeyWordModel keyWordModel = catchKeyWord.getModel();//训练完毕获取模型并将其序列化以JSON字符串形式保存</pre>
                <div class="alert alert-danger" role="alert">
<strong>注意：</strong>语句关键词<code>keyWord</code>必须完全包含于语句<code>code</code>内才有效
<p><code>catchKeyWord</code>需要在服务启动的时候进行单例化。</p>
                </div>
                <p class="normTxt">对获取关键词类进行服务启动初始化</p>
                <pre>
                    CatchKeyWord catchKeyWord = new CatchKeyWord();
                    catchKeyWord.insertModel(keyWordModel);//注入训练时的模型(通过JSON反序列化)</pre>
                <p class="normTxt">对用户输入语句的关键词进行捕捉</p>
                <pre>List&lt;String&gt; keyWords=catchKeyWord.getKeyWord(sen);//返回关键词集合</pre>
                <div class="alert alert-danger" role="alert"><strong>注意：</strong>
                    <code>catchKeyWord</code>从上文服务器初始化中单例的CatchKeyWord获取
                </div>
                <p class="normTxt" id="word">对用户输入的语句进行延伸</p>
                <div class="alert alert-success" role="alert">这通常用在因为用户输入语句过短，或者与你拥有的模板语句差别过大导致无法判断分类的情况。
                这需要我们配合切词使用，若切词数量小于3，我们通常认为该条语句符合上述情况。</div>
                <pre>
List&lt;String&gt; sentenceList = new ArrayList&lt;&gt;();//模板中所有语句集合
                    static{
                      将模板中所有语句集合注入到sentenceList当中
                    }
SentenceCreator creator =new SentenceCreator();//词句延伸类 需要服务启动时单例化
WordTemple wordTemple = new WordTemple();//同上文模板类需要服务启动时单例化
creator.initFirst(sentenceList, wordTemple);
creator.study();//进行训练
String myModel = JSONObject.toJSONString(creator.getModel());//训练完成将模型反序列化为JSON字符串保存
            </pre>
                <div class="alert alert-danger" role="alert"><strong>注意：</strong>
                    <code>creator</code>词句延伸类，需要服务启动时单例化保存
                </div>
                <p class="normTxt">
                    对语句延伸类进行初始化</p>
                <pre>
CreatorSentenceModel model = JSONObject.parseObject(readPaper(file), CreatorSentenceModel.class);
creator.initModel(wordTemple, model);//注入语句延伸模型</pre>
                <div class="alert alert-info" role="alert"><strong>注意：</strong>
                    通过JSON反序列化将<code>CreatorSentenceModel</code>模型注入到<code>creator</code>语句延伸类并单例化，
                    并将<code>CreatorSentenceModel</code>单例保存
                </div>
                <p class="normTxt">若用户语句拆词数量过少，则对用户语句进行延伸生成新的语句</p>
                <pre>
 List&lt;String&gt; words = talk.getSplitWord(sen).get(0);//对该词进行拆词
                if (words.size() < 3) {//拆词数量小于3，则对语句进行补全
                    String fillName = beanMangerOnly.sentenceCreator().fill(sen, talk);//补全语句
                    type = talk.talk(fillName).get(0);//对补全后的语句进行识别
                } else {
                    type = talk.talk(sen).get(0);//对原句进行识别
                }
             </pre>
                <div class="alert alert-warning" role="alert">
                    <strong>拆词数量过少意味着什么：</strong>
                    本框架使用的用户语义理解，为了减少训练量降低训练成本，使用的基本特征是”词“，而不是字。这么做的好处特征更加确定，训练模板数量要求低，落地成本低廉。
                    缺点是如果拆词数量比较少，则缺乏特征使得语义难以理解。为了解决这个问题，本算法流程采用了若拆词数量过少，则对语句进行补全后再进行识别，很大程度的优化了该问题，让用户体验变好。
                    但若用户本身语句拆词数量足够，则没有必要进行这多余的一步，这只会拖慢整体运算的速度。
                </div>
                <h3 id="tools">分类工具</h3>
                <h5 id="nerve">深度神经网络：</h5>
                <pre>
                    //创建一个DNN神经网络管理器
                    /**
     * 初始化神经元参数
     *
     * @param sensoryNerveNub 输入神经元个数
     * @param hiddenNerveNub  隐层神经元个数
     * @param outNerveNub     输出神经元个数
     * @param hiddenDepth     隐层深度
     * @param activeFunction  激活函数
     * @param isDynamic       是否是动态神经元
     * @param isAccurate      是否保留精度
     * @param rzType          正则函数
     * @param lParam          正则系数
     * @throws Exception 如果参数错误则抛异常
     */
    public NerveManager(int sensoryNerveNub, int hiddenNerveNub, int outNerveNub, int hiddenDepth, ActiveFunction activeFunction, boolean isDynamic, boolean isAccurate,
                                double studyPoint, int rzType, double lParam)
    /**
     * 初始化
     *
     * @param initPower 是否是第一次注入
     * @param isMatrix  参数是否是一个矩阵
     * @param isShowLog 是否打印学习参数
     * @param isSoftMax 最后一层是否用softMax激活
     * @throws Exception
     */
     public void init(boolean initPower, boolean isMatrix, boolean isShowLog, boolean isSoftMax)//深度神经网络初始化
     nerveManager.getSensoryNerves()获取感知神经元集合
     //eventId:事件ID
     //parameter:输入特征值
     //isStudy:是否是学习
     //E:特征标注
     //OutBack 回调类
     SensoryNerv.postMessage(long eventId, double parameter, boolean isStudy, Map&lt;Integer, Double&gt; E, OutBack outBack)
     //每一次输出结果都会返回给回调类，通过回调类拿取输出结果，并通过eventId来对应事件
                </pre>
                <div class="alert alert-info" role="alert">
                    构造深度神经网络管理器，初始化，发送参数。输出神经元是通过回调类返回值，回掉类必须实现接口<code>OutBack</code>，通过OutBack实现类获取对应神经元返回参数。
                </div> 
                <h5 id="RF">随机森林：</h5>
                <pre>
                    //创建一个内存中的数据表
                    DataTable dataTable = new DataTable(column);
                    //构造参数是列名集合
                    public DataTable(Set&lt;String&gt; key)
                    //指定主列名集合中该表的主键
                    dataTable.setKey("point");
                    //创建一片随机森林
                    RandomForest randomForest = new RandomForest(7);
                    //构造参数为森林里的树木数量
                    public RandomForest(int treeNub);
                    //唤醒随机森林里的树木
                    randomForest.init(dataTable);
                    //将加入数据的实体类一条条插入森林中
                    randomForest.insert(Object object);
                    //森林进行学习
                    randomForest.study();
                    //插入特征数据，森林对该数据的最终分类结果进行判断
                    int type = randomForest.forest(Object objcet);
                </pre>
                <div class="alert alert-info" role="alert">
                    构造随机森林
                </div> 
                <h5 id="knn">KNN：</h5>
                <pre>
                    public Knn(int nub);//构造参数，有几个人参与投票
                    public void insertMatrix(Matrix vector, int tag);//参数分别是特征向量和类别，注入进KNN当中
                    public int getType(Matrix vector);//输入特征向量，返回类别
                    public void removeType(int type);//移除一个分类
                </pre>
                <div class="alert alert-info" role="alert">
                    构造KNN
                </div> 
                <h3 id="jutools">聚类工具</h3>
                <h5 id="lvq">LVQ学习向量量化：</h5>
                <pre>
                    public LVQ(int typeNub, int lvqNub, double studyPoint);//类别数量，循环次数，学习率，注意lvq的递增类别id必须从0开始
                    public void insertMatrixBody(MatrixBody matrixBody);//注入特征向量
                    public void start()；//执行学习
                </pre>
                <div class="alert alert-info" role="alert">
                    构造LVQ学习向量量化
                </div> 
                <h5 id="kavg">原型聚类：</h5>
                <pre>
                    public MeanClustering(int speciesQuantity);//聚多少个类
                    public void setColor(double[] color);//输入特征数组
                    public void start();//开始聚类
                    public List&lt;RGBNorm&gt; getMatrices();//聚类结束时，获取聚类实体
                </pre>
                <div class="alert alert-info" role="alert">
                    构造原型聚类
                </div>
                <h3 id="arouse">启发式工具</h3>
                <h5 id="pso">粒子群</h5>
                <p class="normTxt">
                    适应函数类需要实现适应函数接口，并实现生成返回值</p>
                <pre>
 public interface PsoFunction {//粒子群回调函数
    //根据参数返回函数值
    double getResult(double[] parameter,int id) throws Exception;
}</pre>
                <p class="normTxt">构造例子群类</p>
                <pre>
              /**
     * 初始化
     *
     * @param dimensionNub 维度
     * @param minBorder  最小边界
     * @param maxBorder 最大边界
     * @param times 迭代次数
     * @param particleNub 粒子数量
     * @param psoFunction 适应函数
     * @param inertialFactor 惯性因子
     * @param selfStudyFactor 个体学习因子
     * @param socialStudyFactor 社会学习因子
     * @param isMax 最大值是否为最优
     * @param maxSpeed 最大速度
     * @param initSpeed 初始速度
     * @throws Exception
     */
    public PSO(int dimensionNub, int[] minBorder, int[] maxBorder,
               int times, int particleNub, PsoFunction psoFunction,
               double inertialFactor, double selfStudyFactor, double socialStudyFactor
            , boolean isMax, double maxSpeed, double initSpeed)
     public void start()//粒子群开始进行迭代
     public double[] getAllBest()//迭代结束获取全局最优解
                </pre>
                <div class="alert alert-info" role="alert">
                  编写适应函数，构造粒子群类，之后进行迭代，迭代完成获取全局最优解。
                </div>
                <h3 id="Intensive">强化学习工具</h3>
                <h5 id="DP">动态规划</h5>
                <p class="normTxt"><strong>动态规划类：</strong><code>DynamicProgramming</code>，
                    动作函数要继承动作抽象类<code>Action</code>，并重写以下方法 </p>
                <pre>
public abstract class Action {//动作
    private int actionId;//动作id

    public int getActionId() {//返回该动作id
        return actionId;
    }

    public void setActionId(int actionId) {//设置该动作id
        this.actionId = actionId;
    }

    public int[] action(int[] stateId) {//stateId状态进行该动作后生成新的状态
        return new int[0];
    }

    public int[] actionTest(int[] stateId) {//stateId状态进行该动作后生成新的测试状态
        return new int[0];
    }

    protected int getProfit(int[] stateId) {//stateId的状态进行该动作后所获得的收益
        return 0;
    }
}
   Map&lt;Integer, Action&gt; actionMap = dynamicProgramming.getActionMap();//从dynamicProgramming获取内部动作集合
}</pre>
                <div class="alert alert-info" role="alert">
                    初始化所有继承动作类的动作函数。然后从dynamicProgramming获取内部动作集合，将初始化的所有动作注入到该集合中，动作id与map主键一一对应。
                </div>
                <p class="normTxt"><strong>状态类：</strong><code>DynamicState</code></p>
                <pre>
public class DynamicState {
    private int[] stateId;//状态id
    private boolean isFinish = false;//是否是终结态
    public void setFinish(boolean finish) {
        isFinish = finish;
    }
    public DynamicState(int[] stateId) {//设置状态id
        this.stateId = stateId;
    }
    List&lt;DynamicState&gt; dynamicStateList = dynamicProgramming.getDynamicStateList();//从dynamicProgramming获取内部状态集合
}</pre>
                <div class="alert alert-info" role="alert">
                    状态类初始化需要通过构造参数，传入状态数组id与该状态是否为终结态。然后从dynamicProgramming获取内部状态集合，将初始化的所有状态注入到该集合中。
                </div>
                <p class="normTxt">启动开始动态规划的策略迭代，并生成价值函数，api调用如下：</p>
                <pre>
    dynamicProgramming.setMaxTimes(int maxTimes)//策略改进最大迭代次数
    dynamicProgramming.setValueTh(double valueTh);//设置策略改进价值阈值
    dynamicProgramming.setGaMa(double gaMa);//设置贴现因子
    dynamicProgramming.gameStart();//开始策略迭代生成价值函数
    dynamicProgramming.getValueFunction();//返回价值函数
    dynamicProgramming.getBestAction(int[] stateId);//获取当前最优动作集合
                </pre>
                <h3 id="matrix">矩阵运算</h3>
                <p class="normTxt"><strong>矩阵类：</strong><code>Matrix</code></p>
                <pre>
                 1,Matrix matrix = new Matrix(int x, int y);//初始化构造一个行为x，列为y的矩阵类
                 2,Matrix matrix= new Matrix(int x, int y, String matr);//初始化构造一个行为x,列为y,内部数据为 matr 的矩阵
                 3,int getX();//获取行数
                 4,int getY();//获取列数
                 5,void setState(int x, int y);//设置矩阵属性，根据x,y的数值大小，属性分别是0矩阵，行矩阵，列矩阵
                 6,double getAVG();//获取当前矩阵中所有数值的平均值
                 7,boolean isRowVector();//该矩阵是否是一个行矩阵
                 8,boolean isVector();该矩阵是否为一个向量
                 9,boolean isZero();该矩阵是否为一个0矩阵
                 10,void clear();//清除矩阵数据
                 11, double getDet();//求该矩阵的行列式
                 12,Matrix getSonOfMatrix(int x, int y, int xSize, int ySize);//求该矩阵的分块矩阵
                 13,Matrix getRow(int x);//求该矩阵指定一行的行向量
                 14,Matrix getColumn(int y);//求该矩阵指定一列的列向量
                 15,String getString();//返回字符串形式的该矩阵
                 16,String getPositionString();//返回带坐标的该矩阵字符串
                 17,void setNub(int x, int y, double number);//向该矩阵指定xy的位置输入一个数值
                 18,double getNumber(int x, int y);//向该矩阵指定xy的位置获取一个数值
                </pre>
                <div class="alert alert-warning" role="alert">
                    <p>2,<code>Matrix matrix= new Matrix(int x, int y, String matr)</code> 示例：
                   <code>Matrix matrix = new Matrix(2, 2, "[1,2]#[3,4]")</code>，构造一个行为2，列为2，第一行数据为[1,2]，第二行数据为[3,4]的矩阵。</p>
                </div>
                <p class="normTxt"><strong>矩阵运算类：</strong><code>MatrixOperation</code></p>
                <pre>
                    static Matrix add(Matrix matrix1, Matrix matrix2);//矩阵相加
                    static Matrix sub(Matrix matrix1, Matrix matrix2);//矩阵相减
                    static Matrix getLinearRegression(Matrix parameter, Matrix out);//多元线性回归
                    static double getEDistByMatrix(Matrix matrix1, Matrix matrix2);//矩阵相似度(欧氏距离)
                    static double getEDist(Matrix matrix1, Matrix matrix2);//两个向量之间欧式距离的平方
                    static Matrix pushVector(Matrix myMatrix, Matrix matrix, boolean addRow);//向一个矩阵里合并一个行向量或者列向量到矩阵行或者列的末尾
                    static Matrix push(Matrix matrix, double nub, boolean isRow);//向一个向量里PUSH一个值
                    static Matrix matrixToVector(Matrix matrix, boolean isRow);//将一个矩阵转成行向量
                    static double innerProduct(Matrix matrix1, Matrix matrix2);//求两个向量的内积
                    static double getNorm(Matrix matrix);//求向量范数
                    static double getNormCos(Matrix matrix1, Matrix matrix2);//求两个向量之间的余弦
                    static Matrix transPosition(Matrix matrix);//矩阵转置
                    static int inverseNumber(double[] myInverse);//逆序数奇偶性判定
                    static Matrix getInverseMatrixs(Matrix matrix);//矩阵求逆
                    static Matrix adjointMatrix(Matrix matrix);//求伴随矩阵
                    static double algebraicCofactor(Matrix matrix, int row, int column);//求矩阵代数余子式
                    static Matrix mulMatrix(Matrix matrix1, Matrix matrix2);//矩阵相乘
                    static void mathMul(Matrix matrix, double nub);//矩阵数乘
                    static void mathSub(Matrix matrix, double nub);//矩阵数减
                    static void mathDiv(Matrix matrix, double nub);//矩阵数除
                    static List&lt;Double&gt; matrixToList(Matrix matrix);//矩阵转list集合
                    static Matrix listToRowVector(List&lt;Double&gt; list);//list集合转行向量
                    static Matrix im2col(Matrix matrix, int kernLen, int step);//卷积im2col
                    static Matrix reverseIm2col(Matrix matrix, int kernLen, int step, int xSize, int ySize);//逆向im2col
                </pre>
                <div class="alert alert-success" role="alert">
                    <p>所有的矩阵运算，返回矩阵都是一个新的实例化矩阵，对参与运算的所有原矩阵原数值不产生任何影响</p>
                </div>
                <h3 id="picture">图像工具</h3>
                <p class="normTxt" id="pictureTools"><strong>图像解析类：</strong><code>Picture</code></p>
                <pre>
                Picture picture = new Picture();//实例化一个图像解析类
                ThreeChannelMatrix getThreeMatrix(String fileURL);//根据本地图片url返回一个RGB三通道矩阵类
                ThreeChannelMatrix getThreeMatrix(InputStream file);//根据一个输入流返回一个RGB三通道矩阵类</pre>
                <div class="alert alert-warning" role="alert">
                    解析图片返回的RGB三通道矩阵类<code>ThreeChannelMatrix</code>，所有像素值都为归一化后的0-1之间的值！
                </div>
                <p class="normTxt"><strong>RGB三通道矩阵：</strong><code>ThreeChannelMatrix</code></p>
                <pre>
    Matrix getMatrixR();//返回R矩阵
    Matrix getMatrixG();//返回G矩阵
    Matrix getMatrixB();//返回B矩阵
    Matrix getH();//返回灰度矩阵</pre>
            </div>
        </div>
    </div>
</body>

</html>